package com.kanshu.service.impl;

import com.kanshu.constant.OnlineType;
import com.kanshu.constant.StatusType;
import com.kanshu.model.Novel;
import com.kanshu.service.NovelService;
import com.kanshu.utils.FileUtil;
import com.kanshu.utils.XmlReader;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.Collection;

/**
 * @author GAIst
 * ClassName NovelServiceImpl.java
 * From
 * Description OK
 * createTime 2024年12月20日14:32:26
 */
public class NovelServiceImpl implements NovelService {
    private static OnlineType onlineType = new OnlineType();
    private static StatusType statusType = new StatusType();
    /**
     * 下载小说功能
     *
     * @param request 用户请求，包含小说索引和类型信息
     * @param out     用于向客户端发送数据的对象输出流
     * @throws IOException 如果文件读写操作失败
     */
    @Override
    public void downloadNovel(Object request, ObjectOutputStream out) throws IOException {
        // 分解请求以获取小说索引和类型
        String[] msg = request.toString().split(",");
        // 1是索引，2是类型

        // 构造小说目录路径
        String path = onlineType.getOUTPUT_TEXT_FATHER_PATH() + msg[2];

        // 查找小说文件的路径
        String novelPath = FileUtil.findFileByPath(path);

        // 根据索引获取小说名称
        String novelName = FileUtil.getFileName(FileUtil.splitNovels(novelPath), Integer.parseInt(msg[1]));

        // 读取小说内容
        String content = FileUtil.getGbFileContent(onlineType.getOUTPUT_TEXT_NOVEL_PATH(path, novelName));

        // 发送小说内容到客户端
        out.writeObject(content);
    }


    /**
     * 读取完整小说内容的方法
     *
     * @param request 用户请求对象，包含小说索引和类型等信息
     * @param out 输出流对象，用于向客户端发送数据
     * @throws IOException 如果文件读取或网络通信发生错误
     */
    @Override
    public void readNovelAll(Object request, ObjectOutputStream out) throws IOException {
        // 分解请求以获取小说索引和类型
        String[] msg = request.toString().split(",");
        //1是索引，2是类型

        // 构造小说目录路径
        String path = onlineType.getOUTPUT_TEXT_FATHER_PATH() + msg[2];

        // 查找小说文件的路径
        String novelPath = FileUtil.findFileByPath(path);

        // 根据索引获取小说名称
        String novelName = FileUtil.getFileName(FileUtil.splitNovels(novelPath), Integer.parseInt(msg[1]));
        // 获取小说内容
        String content;
        if(msg[3] == "1"){
            // 如果是第一页，直接获取前10页的内容
            content = FileUtil.getGbPageContent(onlineType.getOUTPUT_TEXT_NOVEL_PATH(path, novelName), 1, 10);

        }else {
            // 否则，根据指定页码获取10页的内容
            content = FileUtil.getGbPageContent(onlineType.getOUTPUT_TEXT_NOVEL_PATH(path, novelName), Integer.parseInt(msg[3]), 10);
        }
        // 在内容后添加提示信息，用于用户选择下一页或退出
        content = content + "\n下一页请按1，退出请按2：";
        // 将小说内容发送给客户端
        out.writeObject(content);

    }

    /**
     * 根据请求发送小说列表
     * 该方法从XML文件中读取小说信息，并将小说列表以字符串形式发送出去
     *
     * @param request 请求对象，用于指定所需小说列表的类型
     */
    @Override
    public void sendNovelList(Object request, ObjectOutputStream out) {
        // 从指定路径读取XML文件，获取小说列表
        Collection xmlMain = XmlReader.getXmlMain(onlineType.getNOVEL_XML_PATH((String)request));
        // 用于小说列表的编号
        int i = 1;
        // 初始化小说列表消息字符串
        String msg = statusType.getHASNULL();
        // 遍历从XML文件中读取的小说列表
        for (Object o : xmlMain) {
            // 检查对象是否为Novel类型，防止类型错误
            if (o instanceof Novel) {
                // 将小说信息拼接到消息字符串中，包括小说编号、名称、作者和描述
                msg += i + ".\t\t" + ((Novel)o).getName() + "\t\t" + ((Novel)o).getAuthor() + "\t\t" + ((Novel)o).getDescription() + "\n";
                i++; // 编号递增
            }
        }
        // 尝试将小说列表消息发送出去
        try {
            out.writeObject(msg);
        }catch (IOException e) {
            // 如果发生IOException，打印异常信息
            e.printStackTrace();
        }
    }


    /**
     * 向客户端发送小说类型列表
     * 本方法通过ObjectOutputStream对象将小说类型信息写入输出流，以实现向客户端发送小说类型列表的功能
     *
     * @param out ObjectOutputStream对象，用于将小说类型列表输出到客户端
     */
    @Override
    public void sendNovelTypeList(ObjectOutputStream out){
        try {
            // 将小说类型列表作为字符串对象写入输出流
            out.writeObject(new String("1.武侠\n2.言情\n"));
        }catch (IOException e) {
            // 异常处理：打印异常信息栈，以便于问题追踪和定位
            e.printStackTrace();
        }
    }

    /**
     * 读取小说内容
     *
     * @param request 请求对象，包含小说信息
     * @throws IOException 如果读取文件时发生错误
     */
    @Override
    public void readNovel(Object request,ObjectOutputStream out) throws IOException {
        // 分解请求以获取小说索引和类型
        //1是索引，2是类型
        String[] msg = request.toString().split(",");

        // 构造小说目录路径
        String path = onlineType.getOUTPUT_TEXT_FATHER_PATH() + msg[2];

        // 查找小说文件的路径
        String novelPath = FileUtil.findFileByPath(path);

        // 根据索引获取小说名称
        String novelName = FileUtil.getFileName(FileUtil.splitNovels(novelPath), Integer.parseInt(msg[1]));

        // 获取小说内容
        String content = FileUtil.getGbPageContent(onlineType.getOUTPUT_TEXT_NOVEL_PATH(path, novelName), 1, 10);

        // 创建在线类型对象用于获取结束行和选择列表
        OnlineType onlineType = new OnlineType();

        // 构造最终输出结果
        String result = content+"\n"+
                onlineType.getOUTPUT_SIGN_ENDLINE()+"\n"+
                onlineType.getOUTPUT_TEXT_SELECTLIST()+"\n";

        // 写入输出流
        out.writeObject(result);
    }

    /**
     * 上传小说功能实现
     * 此方法处理小说上传请求，根据请求信息检查小说是否已存在，如果不存在则保存小说信息到指定路径
     *
     * @param request 请求对象，包含小说信息字符串，格式为"0.上传小说1.小说类型2.小说名称3.小说作者4.小说简介5.小说路径"，各部分信息间用"*"分隔
     * @param out 输出流对象，用于向客户端发送上传状态信息
     * @throws IOException 如果文件操作或流操作发生错误，抛出此异常
     */
    @Override
    public void uploadNovel(Object request, ObjectOutputStream out) throws IOException {
        // 分解请求字符串，提取小说信息
        String[] msg = request.toString().split("\\*");

        // 构造小说保存路径
        String novelPath = onlineType.getOUTPUT_TEXT_FATHER_PATH()+msg[1];

        // 检查指定路径下是否存在相同名称的小说
        if(FileUtil.findEqualsFileByPath(novelPath,msg[2])){
            // 如果存在，向客户端发送提示信息，表示小说已存在
            out.writeObject(statusType.getHASNULL());
        }else {
            // 如果不存在，尝试保存小说信息
            if (FileUtil.saveNovel(novelPath,msg[1],msg[2],msg[3],msg[4])){
                // 保存成功，向客户端发送提示信息
                out.writeObject(statusType.getHASNULL());
            }else {
                // 保存失败，向客户端发送提示信息
                out.writeObject(statusType.getHASNULL());
            }
        }
    }


}
